using System;
using System.Collections;
using System.Collections.Generic;
using HerenityCode.Reference.SingletonPattern;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.XR;

namespace HerenityCode.Tool
{
    namespace PicoInputManager
    {
        /// <summary>
        /// Description:
        /// Author:哒先生
        /// Date:
        /// </summary>
        public class InputManager : SingletonPatternMonoAutoBase<InputManager>
        {
            //*************输入设别**************************
            InputDevice leftHandController;
            InputDevice rightHandController;
            InputDevice headController;

            //**************对外提供公开事件******************

            #region public event

            public Action onLeftTriggerDown;
            public Action onLeftTriggerHold;
            public Action onLeftTriggerUp;

            public Action onRightTriggerDown;
            public Action onRightTriggerHold;
            public Action onRightTriggerUp;

            public Action onLeftGripDown;
            public Action onLeftGripHold;
            public Action onLeftGripUp;

            public Action onRightGripDown;
            public Action onRightGripHold;
            public Action onRightGripUp;

            public Action onLeftAppButtonDown;
            public Action onLeftAppButtonHold;
            public Action onLeftAppButtonUp;

            public Action onRightAppButtonDown;
            public Action onRightAppButtonHold;
            public Action onRightAppButtonUp;

            public Action onLeftJoyStickDown;
            public Action onLeftJoyStickHold;
            public Action onLeftJoyStickUp;

            public Action onRightJoyStickDown;
            public Action onRightJoyStickHold;
            public Action onRightJoyStickUp;

            public Action<Vector2> onLeftJoyStickMove;
            public Action<Vector2> onRightJoyStickMove;

            public Action onLeftAXButtonDown;
            public Action onLeftAXButtonHold;
            public Action onLeftAXButtonUp;

            public Action onLeftBYButtonDown;
            public Action onLeftBYButtonHold;
            public Action onLeftBYButtonUp;

            public Action onRightAXButtonDown;
            public Action onRightAXButtonHold;
            public Action onRightAXButtonUp;

            public Action onRightBYButtonDown;
            public Action onRightBYButtonHold;
            public Action onRightBYButtonUp;

            #endregion

            //提供状态字典独立记录各个feature的状态
            Dictionary<string, bool> stateDic;

            private void Init()
            {
                if (!leftHandController.isValid)
                {
                    leftHandController = InputDevices.GetDeviceAtXRNode(XRNode.LeftHand);
                }

                if (!rightHandController.isValid)
                {
                    rightHandController = InputDevices.GetDeviceAtXRNode(XRNode.RightHand);
                }

                if (!headController.isValid)
                {
                    headController = InputDevices.GetDeviceAtXRNode(XRNode.Head);
                }

                stateDic = new Dictionary<string, bool>();
            }

            //*******************事件源的触发**************************
            /// <summary>
            /// 按钮事件源触发模板
            /// </summary>
            /// <param name="device">设备</param>
            /// <param name="usage">功能特征</param>
            /// <param name="btnDown">开始按下按钮事件</param>
            /// <param name="btnHold">按下按钮事件</param>
            /// <param name="btnUp">抬起按钮事件</param>
            private void ButtonDispatchModel(InputDevice device, InputFeatureUsage<bool> usage, Action btnDown,
                Action btnHold, Action btnUp)
            {
                //Debug.Log("usage:" + usage.name);
                //为首次执行的feature添加bool状态 -- 用以判断Down和Up状态
                string featureKey = device.characteristics + usage.name;
                if (!stateDic.ContainsKey(featureKey))
                {
                    stateDic.Add(featureKey, false);
                }

                bool isHold;
                if (device.TryGetFeatureValue(usage, out isHold) && isHold)
                {
                    //Debug.Log("device:" + device.characteristics + "usage:" + usage.name);
                    if (!stateDic[featureKey])
                    {
                        stateDic[featureKey] = true;
                        btnDown?.Invoke();
                    }

                    btnHold?.Invoke();
                }
                else
                {
                    if (stateDic[featureKey])
                    {
                        btnUp?.Invoke();
                        stateDic[featureKey] = false;
                    }
                }
            }

            /// <summary>
            /// 摇杆事件源触发模板
            /// </summary>
            /// <param name="device">设备</param>
            /// <param name="usage">功能特征</param>
            /// <param name="joyStickMove">移动摇杆事件</param>
            private void JoyStickDispatchModel(InputDevice device, InputFeatureUsage<Vector2> usage,
                Action<Vector2> joyStickMove)
            {
                Vector2 axis;
                if (device.TryGetFeatureValue(usage, out axis) && !axis.Equals(Vector2.zero))
                {
                    if (joyStickMove != null)
                        joyStickMove(axis);
                }
            }

            //******************每帧轮询监听事件***********************
            private void FixedUpdate()
            {
                if (leftHandController.isValid)
                {
                    ButtonDispatchModel(leftHandController, CommonUsages.triggerButton, onLeftTriggerDown,
                        onLeftTriggerHold, onLeftTriggerUp);
                    ButtonDispatchModel(leftHandController, CommonUsages.gripButton, onLeftGripDown, onLeftGripHold,
                        onLeftGripUp);
                    ButtonDispatchModel(leftHandController, CommonUsages.primaryButton, onLeftAXButtonDown,
                        onLeftAXButtonHold, onLeftAXButtonUp);
                    ButtonDispatchModel(leftHandController, CommonUsages.secondaryButton, onLeftBYButtonDown,
                        onLeftBYButtonHold, onLeftBYButtonUp);
                    ButtonDispatchModel(leftHandController, CommonUsages.primary2DAxisClick, onLeftJoyStickDown,
                        onLeftJoyStickHold, onLeftJoyStickUp);
                    ButtonDispatchModel(leftHandController, CommonUsages.menuButton, onLeftAppButtonDown,
                        onLeftAppButtonHold, onLeftAppButtonUp);
                    JoyStickDispatchModel(leftHandController, CommonUsages.primary2DAxis, onLeftJoyStickMove);
                }
                else
                {
                    Init();
                }

                if (rightHandController.isValid)
                {
                    ButtonDispatchModel(rightHandController, CommonUsages.triggerButton, onRightTriggerDown,
                        onRightTriggerHold, onRightTriggerUp);
                    ButtonDispatchModel(rightHandController, CommonUsages.gripButton, onRightGripDown, onRightGripHold,
                        onRightGripUp);
                    ButtonDispatchModel(rightHandController, CommonUsages.primaryButton, onRightAXButtonDown,
                        onRightAXButtonHold, onRightAXButtonUp);
                    ButtonDispatchModel(rightHandController, CommonUsages.secondaryButton, onRightBYButtonDown,
                        onRightBYButtonHold, onRightBYButtonUp);
                    ButtonDispatchModel(rightHandController, CommonUsages.primary2DAxisClick, onRightJoyStickDown,
                        onRightJoyStickHold, onRightJoyStickUp);
                    ButtonDispatchModel(rightHandController, CommonUsages.menuButton, onRightAppButtonDown,
                        onRightAppButtonHold, onRightAppButtonUp);
                    JoyStickDispatchModel(rightHandController, CommonUsages.primary2DAxis, onRightJoyStickMove);
                }
                else
                {
                    Init();
                }
            }
        }
    }
}